package com.newworld.basketballfire.main.business;

import com.newworld.basketballfire.main.api.Const;
import com.newworld.basketballfire.main.api.DuesType;
import com.newworld.basketballfire.main.api.ErrorCode;
import com.newworld.basketballfire.main.bean.DuesListParam;
import com.newworld.basketballfire.main.dao.DuesDao;
import com.newworld.basketballfire.main.dao.UserDao;
import com.newworld.basketballfire.main.utils.CommonUtils;
import com.newworld.basketballfire.main.utils.InputChecker;
import com.newworld.basketballfire.service.exception.ServiceException;
import com.newworld.basketballfire.service.model.Dues;
import com.newworld.basketballfire.service.model.ListResult;
import com.newworld.basketballfire.service.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by George on 2019/3/3.
 * DuesBusiness
 */
@Component
public class DuesBusiness {

    private static Logger logger = LoggerFactory.getLogger(DuesBusiness.class);

    @Autowired
    private DuesDao duesDao;

    @Autowired
    private UserDao userDao;

    public Dues addDues(Dues dues) throws ServiceException {
        checkDuesType(dues.getType());
        User user = checkUserIdAndGetUser(dues.getUserId());

        adjustDuesValue(dues);

        dues.setId(CommonUtils.getUUID());
        dues.setActivityId(Const.DEFAULT_ACTIVITY_ID);
        long currentTime = CommonUtils.getCurrentTime();
        dues.setLastUpdateTime(currentTime);
        dues.setVersion(Const.DEFAULT_VERSION);

        BigDecimal newDues = user.getDues();
        newDues = newDues.add(dues.getDues());
        user.setDues(newDues);

        duesDao.addDues(dues, user);

        return dues;
    }

    private void adjustDuesValue(Dues dues) {
        dues.setDues(CommonUtils.adjustDuesValue(dues.getType(), dues.getDues()));
    }

    private void checkDuesType(int type) throws ServiceException {
        if (type != DuesType.CONSUME.getValue()
                && type != DuesType.RECHARGE.getValue()) {
            logger.error("dues type is invalid.");
            throw new ServiceException(HttpStatus.BAD_REQUEST, ErrorCode.INVALID_PARAMS, "dues type is invalid.");
        }
    }

    public Dues updateDues(Dues dues) throws ServiceException {
        checkDuesCanBeUpdated(dues, "cannot update or delete the dues of activity.");
        checkDuesType(dues.getType());

        Dues oldDues = checkIdAndGetDues(dues.getId());
        User user = checkUserIdAndGetUser(dues.getUserId());
        if (!oldDues.getUserId().equals(user.getId())) {
            logger.error("the user id of dues can not be allowed to change.");
            throw new ServiceException(HttpStatus.BAD_REQUEST, ErrorCode.INVALID_PARAMS, "the user id of dues can not be allowed to change.");
        }

        adjustDuesValue(dues);

        BigDecimal newDues = user.getDues();
        newDues = newDues.add(dues.getDues()).subtract(oldDues.getDues());
        user.setDues(newDues);

        dues.setVersion(oldDues.getVersion());
        dues.setLastUpdateTime(CommonUtils.getCurrentTime());

        duesDao.updateDues(dues, user);
        return oldDues;
    }

    private void checkDuesCanBeUpdated(Dues dues, String errorInfo) throws ServiceException {
        if (!StringUtils.isEmpty(dues.getActivityId()) && !Const.DEFAULT_ACTIVITY_ID.equals(dues.getActivityId())) {
            logger.error(errorInfo);
            throw new ServiceException(HttpStatus.BAD_REQUEST, ErrorCode.INVALID_PARAMS, errorInfo);
        }
    }

    private User checkUserIdAndGetUser(String userId) throws ServiceException {
        User user = userDao.getUser(userId);
        if (user == null || !user.getId().equals(userId)) {
            logger.error("user not exist.");
            throw new ServiceException(HttpStatus.BAD_REQUEST, ErrorCode.INVALID_PARAMS, "user not exist.");
        }
        return user;
    }

    private Dues checkIdAndGetDues(String id) throws ServiceException {
        Dues oldDues = duesDao.getDues(id);
        if (oldDues == null || !oldDues.getId().equals(id)) {
            logger.error("dues not exist.");
            throw new ServiceException(HttpStatus.BAD_REQUEST, ErrorCode.INVALID_PARAMS, "dues not exist.");
        }
        return oldDues;
    }

    public void deleteDues(String id) throws ServiceException {
        Dues dues = checkIdAndGetDues(id);
        User user = checkUserIdAndGetUser(dues.getUserId());

        checkDuesCanBeUpdated(dues, "cannot delete the dues of activity.");

        BigDecimal newDues = user.getDues();
        newDues = newDues.subtract(dues.getDues());
        user.setDues(newDues);

        duesDao.deleteDues(dues, user);
    }

    public Dues getDues(String id) throws ServiceException {
        return duesDao.getDues(id);
    }

    public ListResult<Dues> getDuesList(DuesListParam duesListParam) throws ServiceException {
        InputChecker.checkPageSizeAndNo(duesListParam.getPageNo(), duesListParam.getPageSize());

        int curIndex = (duesListParam.getPageNo() - 1) * duesListParam.getPageSize();
        duesListParam.setCurIndex(curIndex);

        ListResult<Dues> duesListResult = new ListResult<>();
        duesListResult.setPageSize(duesListParam.getPageSize());
        duesListResult.setPageNo(duesListParam.getPageNo());

        int totalCnt = duesDao.getDuesListTotalCnt(duesListParam);
        duesListResult.setTotalCnt(totalCnt);

        List<Dues> dues;
        if (totalCnt > 0) {
            dues = duesDao.getDuesList(duesListParam);
        } else {
            dues = new ArrayList<>();
        }
        duesListResult.setData(dues);

        return duesListResult;
    }


}
